package timer

import (
	"sync"
)

// 任务节点缓存池
var tasknNodePool = &sync.Pool{
	New: func() any {
		return new(taskNode)
	},
}

// 定时任务列表结构体
type taskList struct {
	mu sync.Mutex

	// 任务链表
	head *taskNode
}

// 链表节点
type taskNode struct {
	// 下一个节点
	next *taskNode

	// 节点过期时间
	expireTime uint64

	// 节点任务
	task *task
}

// 往链表中插入一个节点
func (n *taskNode) Insert(target *taskNode) {
	// 插入遵循由小到大的时间顺序,时间相同时先到先得
	// 插入时存在3种情况:
	// 1. 当前节点是尾节点: 目标节点置为尾节点
	// 2. 目标节点 <  下一个节点: 插入目标节点到当前节点之后
	// 3. 目标节点 >= 下一个节点: 前往下一个节点处理
	if n.next == nil {
		n.next = target
	} else if target.expireTime < n.next.expireTime {
		target.next = n.next
		n.next = target
	} else {
		n.next.Insert(target)
	}
}

// 获取链表长度
func (tl *taskList) Len() (length int) {
	tl.mu.Lock()
	defer tl.mu.Unlock()

	node := tl.head
	for node != nil {
		length++
		node = node.next
	}

	return
}

// 添加定时任务
func (tl *taskList) Add(expireTime uint64, task *task) {
	target := tasknNodePool.Get().(*taskNode)
	target.next = nil
	target.expireTime = expireTime
	target.task = task

	tl.mu.Lock()
	defer tl.mu.Unlock()

	if tl.head == nil {
		tl.head = target
	} else if target.expireTime < tl.head.expireTime {
		target.next = tl.head
		tl.head = target
	} else {
		tl.head.Insert(target)
	}
}

// 提取过期任务
func (tl *taskList) Expire(expireTime uint64, tasks *[]*task) {
	var nodes []*taskNode

	tl.mu.Lock()
	node := tl.head
	for node != nil {
		if node.expireTime <= expireTime {
			nodes = append(nodes, node)
			node = node.next
		} else {
			break
		}
	}
	tl.head = node
	tl.mu.Unlock()

	for _, node := range nodes {
		*tasks = append(*tasks, node.task)

		node.task = nil
		node.next = nil
		tasknNodePool.Put(node)
	}
}

// 清空列表上的定时任务
func (tl *taskList) Clear(tasks *[]*task) {
	tl.mu.Lock()
	node := tl.head
	tl.head = nil
	tl.mu.Unlock()

	for node != nil {
		*tasks = append(*tasks, node.task)

		next := node.next
		node.task = nil
		node.next = nil
		tasknNodePool.Put(node)

		node = next
	}
}
